import numpy as np
import scipy.stats as pd
import random
import copy

totalnum=604
ssampleCount=61

def getExamDistribution(score,ranking): # 均为两个元素的np数组
    x2 = score # x2
    cd = 1 - (ranking / totalnum)

    snormal=pd.norm(0,1)
    x1=np.array([snormal.ppf(cd[0]),snormal.ppf(cd[1])])
    # 有转换公式：x1=(x2-mu2)/sigma2
    mu2=(x1[0]*x2[1]-x2[0]*x1[1])/(x1[0]-x1[1])
    if x1[0]!=0:
        sigma2 = (x2[0] - mu2) / x1[0]
    else:
        sigma2 = (x2[1] - mu2) / x1[1]

    result=np.array([mu2,sigma2])
    return result

def isRepeat(list):
    for i in range(len(list)):
        for j in range(i+1,len(list)):
            if list[i]==list[j]:
                return True
    return False

# 设读入的为(ssampleCount,2)的np矩阵和(ssampleCount,)的np数组，2为成绩和时间，下标对应学号
def dropout(table,trank): # 调用此函数一次生成一组样本标签对
    count=random.randint(4, 15) # 留存多少
    sublist=None
    while 1:
        sublist = random.sample(range(ssampleCount), count)
        if not isRepeat(sublist):
            break

    sample = np.zeros((ssampleCount,2))
    for sub in sublist:
        sample[sub]=table[sub]
    for i in range(ssampleCount):
        sample[i][1]=table[0][1]

    # 寻找离实际正态分布中心最近的点
    min1={"sub":0,"error":(totalnum/2)-2}
    min2={"sub":0,"error":(totalnum/2)-1}
    for sub in sublist:
        nowerror=abs(trank[sub]-(totalnum/2))
        if nowerror<min1["error"]:
            min2=copy.copy(min1)
            min1["sub"]=sub
            min1["error"]=nowerror
            continue
        if nowerror<min2["error"]:
            min2["sub"]=sub
            min2["error"]=nowerror

    # 进行参数计算
    sub1=min1["sub"]
    sub2=min2["sub"]
    score = np.array([table[sub1][0], table[sub2][0]])
    ranking = np.array([trank[sub1], trank[sub2]])
    result=getExamDistribution(score,ranking)

    return {"sample":sample,"result":result}

def caluRank(par,x):
    snormal=pd.norm(par[0],par[1])
    return (1 - snormal.cdf(x)) * totalnum